package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.menu.InitJxcMenuHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.pojo.AccordConfigMenuPojo;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.script.help.ScriptEsHelper;
import com.xbongbong.paas.script.pojo.ListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.flowbill.dto.FlowBillInsertDTO;
import com.xbongbong.pro.product.pojo.dto.CostRecalculationDTO;
import com.xbongbong.pro.rabbitmq.producer.CostRecalculationProducer;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BatchFlowBillEntity;
import com.xbongbong.saas.domain.entity.BatchSurplusRecordEntity;
import com.xbongbong.saas.domain.entity.CostAdjustProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.StockFlowBillEntity;
import com.xbongbong.saas.domain.entity.StockSurplusRecordEntity;
import com.xbongbong.saas.domain.entity.WarehouseOristockEntity;
import com.xbongbong.saas.domain.entity.WarehouseOristockProductEntity;
import com.xbongbong.saas.domain.entity.ext.CostAdjustEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.StockTypeEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.subform.ProductStockSubFormEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.model.BatchFlowBillModel;
import com.xbongbong.saas.model.BatchSurplusRecordModel;
import com.xbongbong.saas.model.CostAdjustModel;
import com.xbongbong.saas.model.CostAdjustProductModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.StockFlowBillModel;
import com.xbongbong.saas.model.StockSurplusRecordModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WarehouseOristockModel;
import com.xbongbong.saas.model.WarehouseOristockProductModel;
import com.xbongbong.saas.service.BatchFlowBillService;
import com.xbongbong.saas.service.StockFlowBillService;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 处理新成本方案流水脚本<p>
 * 代码描述<p>
 * Company: 逍邦网络科技有限公司<p>
 *
 * @author ruansicheng
 * @version v1.0
 * @since 2021-11-30 14:33
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/stockFlowBill")
public class StockFlowBillScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(StockFlowBillScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private InitJxcMenuHelp initJxcMenuHelp;
    @Resource
    private StockSurplusRecordModel stockSurplusRecordModel;
    @Resource
    private StockFlowBillService stockFlowBillService;
    @Resource
    private BatchFlowBillService batchFlowBillService;
    @Resource
    private BatchSurplusRecordModel batchSurplusRecordModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private StockFlowBillModel stockFlowBillModel;
    @Resource
    private BatchFlowBillModel batchFlowBillModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private CostAdjustProductModel costAdjustProductModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private CostAdjustModel costAdjustModel;
    @Resource
    private WarehouseOristockProductModel warehouseOristockProductModel;
    @Resource
    private WarehouseOristockModel warehouseOristockModel;
    @Resource
    private CostRecalculationProducer costRecalculationProducer;
    @Resource
    private ScriptEsHelper scriptEsHelper;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private WarehouseModel warehouseModel;



    /**
     * 进销存的公司插入临时表
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/initJxcCorpidList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initJxcCorpidList(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("开启进销存的公司插入临时表  begin。。。。。。。");
        //支持传入公司
        long start = DateTimeUtil.getInt();
        //获取满足条件的公司ID
        //获取符合条件的公司-现在开启进销存公司列表
        List<String> corpidList = companyModel.getJxcCorpidList();
        LOG.warn("共有公司" + corpidList.size() + "家");
        if (!corpidList.isEmpty()) {
            int pageSize = 1000;
            int totalCount = corpidList.size();
            int page = 0;
            while (true) {
                if ((page + 1) * pageSize >= totalCount) {
                    companyModel.insertBatch(corpidList.subList(page * pageSize, totalCount));
                    break;
                } else {
                    companyModel.insertBatch(corpidList.subList(page * pageSize, (page + 1) * pageSize));
                }
                page++;
                LOG.warn("1000家公司刷入进销存的公司插入临时表！");
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("进销存的公司插入临时表 结束！");
        return "success";
    }

    /**
     * 处理未开启流水，已开启进销存的公司开启流水设置-菜单等
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/resetting", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String resettingSstockFlowBill(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("开启流水菜单配置  begin。。。。。。。");
        //支持传入公司
        long start = DateTimeUtil.getInt();
        List<String> corpidList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList())) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else {
            //获取满足条件的公司ID
            //获取符合条件的公司-现在开启进销存公司列表
            corpidList = companyModel.getJxcCorpidListTemporary();
        }
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            try {
                //获取流水配置
                String alias = CompanyConfigEnum.ENABLE_STOCK_FLOW_BILL.getAlias();
                CompanyConfigEnum configEnum = CompanyConfigEnum.getByAlias(alias);
                CompanyConfigEntity companyConfigEntity=new CompanyConfigEntity(corpid, configEnum.getName(), alias, BasicConstant.IS_USE.toString());
                //开启菜单
                AccordConfigMenuPojo accordConfigMenuPojo = new AccordConfigMenuPojo();
                accordConfigMenuPojo.setCorpid(corpid);
                accordConfigMenuPojo.setConfigEntity(companyConfigEntity);
                accordConfigMenuPojo.setConfigValue(BasicConstant.IS_USE.toString());
                accordConfigMenuPojo.setConfigEnum(configEnum);
                accordConfigMenuPojo.setPlatform(PlatFormEnum.WEB.getValue());
                accordConfigMenuPojo.setUserId("system");
                initJxcMenuHelp.addAccordConfigMenu(accordConfigMenuPojo);
            } catch (Exception e) {
                LOG.error("失败了,公司ID是" + corpid + "错误信息" + e);
            }
            ++corpidCount;
            LOG.warn("公司:" + corpid + "-------" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("生成菜单 结束！");
        return "success";
    }

    /**
     * 为所有开启进销存的公司重新刷流水
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addAllStockFlowBill", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String addAllStockFlowBill(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("生成流水 begin。。。。。。。");
        long start = DateTimeUtil.getInt();
        List<String> corpidList = new ArrayList<>();
        List<String> errorCorpidList = new ArrayList<>();
        Integer type = null;
        if (Objects.nonNull(fixDataJobDTO.getType())) {
            type = fixDataJobDTO.getType();
        }
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList()) && fixDataJobDTO.getCorpidList().size() == 1) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        LOG.warn("查询进销存公司列表结束，花费时间:" + (DateTimeUtil.getInt() - start));
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        //处理的次数
        //double count = Math.ceil(Double.valueOf(corpidList.size()) / size);
        //分页循环处理公司
        //获取6个月前时间----为了刷当前时间半年内流水数据
        Long sixMonthAgo = DateTimeUtil.getTimestampByCalendarType(DateTimeUtil.getTodayInt(), -6, Calendar.MONTH);
        if (Objects.nonNull(fixDataJobDTO.getDay())){
            sixMonthAgo = DateTimeUtil.getTimestampByCalendarType(DateTimeUtil.getTodayInt(), -fixDataJobDTO.getDay().intValue(), Calendar.MONTH);
        }
        LOG.warn("刷流水生成的开始日期:" + sixMonthAgo);
        Long beforeSeconds = DateTimeUtil.getTodayInt() - sixMonthAgo;
   /* Map<String, Object> param = new HashMap<>(16);
    param.put("del", 0);*/
        //for (int i = 1; i <= count; i++) {
        //List<String> corpids = corpidList.stream().skip((i - 1) * size).limit(size).collect(Collectors.toList());
        //区分公司是否有效
        /*if (Objects.nonNull(type)){
            param.put("corpidIn", corpidList);
            param.put("status", type);
            List<CompanyEntity> companyEntities=companyModel.findEntitys(param);
            corpids = companyEntities.stream().map(CompanyEntity::getCorpid).collect(Collectors.toList());
        }*/
        Map<String, Object> param=new HashMap<>();
        //单位秒
        Long todayInt = DateTimeUtil.getTodayInt();
        Long greaterThanDate= todayInt - beforeSeconds;
        param.put("greaterThanDate",greaterThanDate);
        if (CollectionsUtil.isNotEmpty(corpidList)) {
            Map<String, Object> paraMap = new HashMap<>();
            paraMap.put("date", sixMonthAgo);
            paraMap.put("corpidIn", corpidList);
            param.put("corpid",corpidList.get(0));
            // 先删除后添加
            stockFlowBillModel.deleteByAddTime(param);
            batchFlowBillModel.deleteByAddTime(param);
            stockSurplusRecordModel.deleteByAddTime(param);
            batchSurplusRecordModel.deleteByAddTime(param);
            //初始化结余表数据
            // 插入当前分仓，往前推流水，后面会更新
            stockSurplusRecordModel.batchInsertRecordsFromProductWarehouse(paraMap);
            // 插入，往前推批次流水，后面会更新
            batchSurplusRecordModel.batchInsertRecordsFromBatchStock(paraMap);
            //每家公司生成流水
            for (String corpid : corpidList) {
                LOG.warn("公司:" + corpid + "-------" + "开始刷入数据");
                long startTmie = DateTimeUtil.getInt();
                try {
                    FlowBillInsertDTO flowBillInsertDTO = new FlowBillInsertDTO();
                    flowBillInsertDTO.setCorpid(corpid);
                    flowBillInsertDTO.setBeforeSeconds(beforeSeconds);
                    flowBillInsertDTO.setCorpid(corpid);
                    stockFlowBillService.insertBeforeStockFlow(flowBillInsertDTO);
                    batchFlowBillService.insertBeforeBatchFlow(flowBillInsertDTO);
                } catch (Exception e) {
                    errorCorpidList.add(corpid);
                    LOG.error("公司" + corpid + "失败了" + e);
                }
                ++corpidCount;
                long endTmie = DateTimeUtil.getInt() - startTmie;
                LOG.warn("公司:" + corpid + "刷入完成------耗时: " + endTmie + "秒,总进度为："  + corpidCount + "/" + corpidList.size());
            }
        }
        //}
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("失败的公司:" + errorCorpidList.toString());
        LOG.warn("生成流水 结束！");
        return "success";
    }

    /**
     * 修复成本为null
     * 只适用于没有流水数据，结账修复不了的情况
     * @param fixDataJobDTO
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/repairCost", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairCost(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("开始修复成本  begin。。。。。。。");
        //支持传入公司
        long start = DateTimeUtil.getInt();
        List<String> corpidList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList())) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else {
            //获取满足条件的公司ID
            //获取符合条件的公司-现在开启进销存公司列表
            corpidList = companyModel.getJxcCorpidListTemporary();
        }
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            try {
                //获取成本为null的产品id
                List<Long> productIdList = new ArrayList<>();
                List<String> warehouseKeyList = new ArrayList<>();
                Map<String, ProductWarehouseEntity> productWarehouseEntityMap = new HashMap<>();
                List<ProductWarehouseEntity> productWarehouseList = new ArrayList<>();
                List<String> batchKeyList = new ArrayList<>();
                List<ProductStockEntity> productStockList = new ArrayList<>();
                Map<String, ProductStockEntity> productStockEntityMap = new HashMap<>();
                List<ProductEntityExt> productEntityExtList = productModel.getCostIsNullProduct(corpid);
                productEntityExtList.forEach(productEntityExt -> {
                    productIdList.add(productEntityExt.getId());
                });
                //获取成本为null的产品所在分仓成本为空的warehouse_key
                List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.getCostIsNullWarehouseKey(corpid, productIdList);
                //获取成本为null的产品所在批次成本为空的batch_key
                List<ProductStockEntity> productStockEntityList = productStockModel.getCostIsNullBatchKey(corpid, productIdList);
                //获取库存流水
                productWarehouseEntityList.forEach(productWarehouseEntity -> {
                    warehouseKeyList.add(productWarehouseEntity.getWarehouseKey());
                    productWarehouseEntityMap.put(productWarehouseEntity.getWarehouseKey(),productWarehouseEntity);
                });
                List<StockFlowBillEntity> stockFlowBillEntityList = stockFlowBillModel.getStockFlowByWarehouseKey(corpid, warehouseKeyList);
                stockFlowBillEntityList.forEach(stockFlowBillEntity -> {
                    ProductWarehouseEntity productWarehouseEntity = productWarehouseEntityMap.get(stockFlowBillEntity.getWarehouseKey());
                    productWarehouseEntity.setCost(stockFlowBillEntity.getProductCost());
                    Double totalCost = Arith.mul(productWarehouseEntity.getNum(), stockFlowBillEntity.getProductCost());
                    productWarehouseEntity.setTotalCost(totalCost);
                });
                for (String warehouseKey : productWarehouseEntityMap.keySet()){
                    productWarehouseList.add(productWarehouseEntityMap.get(warehouseKey));
                }
                //获取批次流水
                productStockEntityList.forEach(productStockEntity -> {
                    batchKeyList.add(productStockEntity.getBatchKey());
                    productStockEntityMap.put(productStockEntity.getBatchKey(), productStockEntity);
                });
                List<BatchFlowBillEntity> batchFlowBillEntityList = batchFlowBillModel.getBatchFlowByBatchKey(corpid, batchKeyList);
                batchFlowBillEntityList.forEach(batchFlowBillEntity -> {
                    ProductStockEntity productStockEntity = productStockEntityMap.get(batchFlowBillEntity.getBatchKey());
                    productStockEntity.setCost(batchFlowBillEntity.getProductCost());
                    Double totalCost = Arith.mul(productStockEntity.getNum(), batchFlowBillEntity.getProductCost());
                    productStockEntity.setTotalCost(totalCost);
                });
                for (String batchKey : productStockEntityMap.keySet()){
                    productStockList.add(productStockEntityMap.get(batchKey));
                }
                //更新分仓成本与数量
                if (CollectionsUtil.isNotEmpty(productWarehouseList)){
                    //更新数据库
                    productWarehouseModel.updateProductWarehouseById(productWarehouseList, corpid);
                    //更新ES
                    List<InsertDTO> updateDTOList = new ArrayList<>();
                    productWarehouseList.forEach(productWarehouseEntity -> {
                        Long productWarehouseId = productWarehouseEntity.getId();
                        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        JSONObject object = new JSONObject();
                        object.put(ProductWarehouseSubFormEnum.COST.getDataAttr(), productWarehouseEntity.getCost());
                        object.put(ProductWarehouseSubFormEnum.TOTAL_COST.getDataAttr(), productWarehouseEntity.getTotalCost());
                        object.put(ProductWarehouseSubFormEnum.NUM.getDataAttr(), productWarehouseEntity.getNum());
                        map.put(StringConstant.JSON_DATA, object);
                        InsertDTO insertDTO = new InsertDTO();
                        insertDTO.setWaitUntil(WriteRequest.RefreshPolicy.NONE);
                        insertDTO.setEsId(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE.getType() + "_" + corpid + "_" + productWarehouseId);
                        insertDTO.setParent(corpid + "_" + productWarehouseEntity.getProductId());
                        insertDTO.setSource(map);
                        insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE);
                        updateDTOList.add(insertDTO);
                    });
                    paasEsModel.updateBatch(updateDTOList, WriteRequest.RefreshPolicy.NONE);
                }
                //更新批次成本与数量
                if (CollectionsUtil.isNotEmpty(productStockList)) {
                    //更新数据库
                    productStockModel.updateProductStockById(productStockList, corpid);
                    //更新ES
                    if (!productStockList.isEmpty()) {
                        List<InsertDTO> updateBatchList = new ArrayList<>();
                        for (ProductStockEntity entity : productStockList) {
                            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            JSONObject object = new JSONObject();
                            object.put(ProductStockSubFormEnum.NUM.getDataAttr(), entity.getNum());
                            object.put(ProductStockSubFormEnum.COST.getDataAttr(), entity.getCost());
                            object.put(ProductStockSubFormEnum.TOTAL_COST.getDataAttr(), entity.getTotalCost());
                            map.put(StringConstant.JSON_DATA, object);
                            InsertDTO insertDTO = new InsertDTO();
                            insertDTO.setWaitUntil(WriteRequest.RefreshPolicy.NONE);
                            insertDTO.setEsId(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getType() + "_" + corpid + "_" + entity.getId());
                            insertDTO.setParent(corpid + "_" + entity.getProductId());
                            insertDTO.setSource(map);
                            insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO);
                            updateBatchList.add(insertDTO);
                        }
                        paasEsModel.updateBatch(updateBatchList, WriteRequest.RefreshPolicy.NONE);
                    }
                }
                //更新产品表
                List<ProductEntityExt> productEntityList = new ArrayList<>();
                List<ProductWarehouseEntity> productWarehouseEntityExtList = productWarehouseModel.findProductWarehouse(productIdList , corpid);
                productWarehouseEntityExtList.forEach(productWarehouseEntity -> {
                    ProductEntityExt productEntityExt = new ProductEntityExt();
                    productEntityExt.setId(productWarehouseEntity.getProductId());
                    productEntityExt.setNum(productWarehouseEntity.getNum());
                    productEntityExt.setTotalCost(productWarehouseEntity.getTotalCost());
                    if (Objects.equals(productWarehouseEntity.getNum().compareTo(0.00) ,0)){
                        productEntityExt.setCost(productWarehouseEntity.getCost());
                    }else {
                        productEntityExt.setCost(Arith.div(productWarehouseEntity.getTotalCost() , productWarehouseEntity.getNum()));
                    }
                    productEntityList.add(productEntityExt);
                });
                productModel.updateProductCostByid(productEntityList, corpid);
                List<UpdateDataEntity> list = new ArrayList<>();
                productEntityList.forEach(productEntityExt -> {
                    UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                    updateDataEntity.setId(productEntityExt.getId());
                    updateDataEntity.setCorpid(corpid);
                    List<UpdateDataValueEntity> data = new ArrayList<>();
                    UpdateDataValueEntity updateDataValueEntity1 = new UpdateDataValueEntity();
                    updateDataValueEntity1.setKey(ProductEnum.COST.getAttr());
                    updateDataValueEntity1.setEsKey(ProductEnum.COST.getAttr());
                    updateDataValueEntity1.setValue(productEntityExt.getCost());
                    data.add(updateDataValueEntity1);
                    UpdateDataValueEntity updateDataValueEntity2 = new UpdateDataValueEntity();
                    updateDataValueEntity2.setKey(ProductEnum.STOCK.getAttr());
                    updateDataValueEntity2.setEsKey(ProductEnum.STOCK.getAttr());
                    updateDataValueEntity2.setValue(productEntityExt.getNum());
                    data.add(updateDataValueEntity2);
                    updateDataEntity.setData(data);
                    list.add(updateDataEntity);
                });
                paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_SAAS_PRODUCT);
            } catch (Exception e) {
                LOG.error("失败了,公司ID是" + corpid + "错误信息" + e);
            }
            ++corpidCount;
            LOG.warn("公司:" + corpid + "-------" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("生成菜单 结束！");
        return "success";
    }

    /**
     * 修复产品流水的数量与成本
     * @param fixDataJobDTO
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/repairFlowProductNumAndCost", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairFlowProductNumAndCost(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("开始修复产品流水的数量与成本  begin。。。。。。。");
        long start = DateTimeUtil.getInt();
        String corpid = fixDataJobDTO.getCorpid();
        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        if (Objects.isNull(corpid) || Objects.isNull(dataIdList)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        //获得产品的所有分仓和批次
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("productIdIn",dataIdList);
        map.put("del", DelEnum.NORMAL.getDel());
        List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysForUpdate(map);
        List<ProductStockEntity> productStockEntityList = productStockModel.findEntitys(map);
        //获取分仓和批次结存信息
        List<StockSurplusRecordEntity> stockSurplusRecordEntityList = stockSurplusRecordModel.findEntitys(map);
        Map<String, StockSurplusRecordEntity> stockSurplusMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        stockSurplusRecordEntityList.forEach(stockSurplusRecordEntity -> {
            stockSurplusMap.put(stockSurplusRecordEntity.getWarehouseKey(), stockSurplusRecordEntity);
        });
        List<BatchSurplusRecordEntity> batchSurplusRecordEntityList = batchSurplusRecordModel.findEntitys(map);
        Map<String, BatchSurplusRecordEntity> batchSurplusMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        batchSurplusRecordEntityList.forEach(batchSurplusRecordEntity -> {
            batchSurplusMap.put(batchSurplusRecordEntity.getBatchKey(), batchSurplusRecordEntity);
        });
        Long time = 0L;
        //处理分仓信息
        List<StockFlowBillEntity> stockFlowBillEntityList = new ArrayList<>();
        List<StockSurplusRecordEntity> stockSurplusRecordEntList = new ArrayList<>();
        for (ProductWarehouseEntity productWarehouseEntity : productWarehouseEntityList){
            Double instockNum = BasicConstant.ZERO_DOUBLE;
            Double outstockNum = BasicConstant.ZERO_DOUBLE;
            Double instockCost= BasicConstant.ZERO_DOUBLE;
            Double outstockCost = BasicConstant.ZERO_DOUBLE;
            //根据出入库时间获取第一条流水
            StockFlowBillEntity stockFlowBillEntity = stockFlowBillModel.getStockFlowBillBytime(corpid, productWarehouseEntity.getProductId(), productWarehouseEntity.getWarehouseId());
            if (Objects.nonNull(stockFlowBillEntity) && (Objects.equals(time, 0L) || time > stockFlowBillEntity.getDate())){
                time = stockFlowBillEntity.getDate();
            }
            //获取所有的出入库关联产品
            Map<String, Object> warehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseMap.put("corpid", corpid);
            warehouseMap.put("productId", productWarehouseEntity.getProductId());
            warehouseMap.put("del", DelEnum.NORMAL.getDel());
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(warehouseMap);
            warehouseMap.put("warehouseId", productWarehouseEntity.getWarehouseId());
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(warehouseMap);
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(warehouseMap);
            List<CostAdjustProductEntity> costAdjustProductEntityList = costAdjustProductModel.findEntitys(warehouseMap);
            //计算入库信息
            if (!instockProductEntityList.isEmpty()) {
                //入库单ID集合
                List<Long> idList = new ArrayList<>();
                //入库单id 集合
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                //获取入库单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(stockFlowBillEntity)){
                    filterMap.put("lessThanDate", stockFlowBillEntity.getDate());
                }
                List<InstockEntityExt> instockEntityList = instockModel.findEntitys(filterMap);
                instockEntityList.forEach(item -> {
                    idList.add(item.getId());
                });
                //计算入库结存
                for (InstockProductEntity instockProductEntity : instockProductEntityList) {
                    //判断该入库产品关联数据对应的入库单ID是否符合生成结存的时间范围
                    if (!idList.contains(instockProductEntity.getIntoWarehouseId())) {
                        continue;
                    }
                    instockNum = Arith.add(instockNum, instockProductEntity.getProductNum());
                    instockCost = Arith.add(instockCost, Arith.mul(instockProductEntity.getCost(), instockProductEntity.getProductNum()));
                }
            }
            //计算出库信息
            if (!outstockProductEntityList.isEmpty()) {
                //出库单ID集合
                List<Long> idList = new ArrayList<>();
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                //获取出库单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(stockFlowBillEntity)){
                    filterMap.put("lessThanDate", stockFlowBillEntity.getDate());
                }
                List<OutstockEntityExt> outstockEntityList = outstockModel.findEntitys(filterMap);
                outstockEntityList.forEach(item -> {
                    idList.add(item.getId());
                });
                for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                    if (!idList.contains(outstockProductEntity.getOutWarehouseId())) {
                        continue;
                    }
                    outstockNum = Arith.add(outstockNum, outstockProductEntity.getProductNum());
                    outstockCost = Arith.add(outstockCost, Arith.mul(outstockProductEntity.getCost(), outstockProductEntity.getProductNum()));
                }
            }
            //计算成本调整单信息
            if (!costAdjustProductEntityList.isEmpty()) {
                //成本调整单ID集合
                List<Long> idList = new ArrayList<>();
                List<Long> costAdjustIdList = new ArrayList<>();
                costAdjustProductEntityList.forEach(item -> costAdjustIdList.add(item.getCostAdjustId()));
                //获取成本调整单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", costAdjustIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(stockFlowBillEntity)){
                    filterMap.put("lessThanDate", stockFlowBillEntity.getDate());
                }
                List<CostAdjustEntityExt> costAdjustEntityExtList = costAdjustModel.findEntitys(filterMap);
                costAdjustEntityExtList.forEach(item -> {
                    idList.add(item.getId());
                });
                for (CostAdjustProductEntity costAdjustProductEntity : costAdjustProductEntityList) {
                    if (!idList.contains(costAdjustProductEntity.getCostAdjustId())) {
                        continue;
                    }
                    instockCost = Arith.add(instockCost, costAdjustProductEntity.getCostAdjustAmount().doubleValue());
                }
            }
            //计算期初信息
            if (!warehouseOristockProductEntityList.isEmpty()) {
                //期初ID集合
                List<Integer> idList = new ArrayList<>();
                List<Integer> oristockIdList = new ArrayList<>();
                warehouseOristockProductEntityList.forEach(item -> oristockIdList.add(item.getOristockId()));
                //获取成本调整单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", oristockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(filterMap);
                warehouseOristockEntityList.forEach(item -> {
                    if(Objects.equals(productWarehouseEntity.getWarehouseId(), item.getWarehouseId())){
                        idList.add(item.getId());
                    }
                });
                for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                    if (!idList.contains(warehouseOristockProductEntity.getOristockId())) {
                        continue;
                    }
                    if (Objects.nonNull(stockFlowBillEntity) && warehouseOristockProductEntity.getAddTime() >= stockFlowBillEntity.getDate()) {
                        continue;
                    }
                    instockNum = Arith.add(instockNum, warehouseOristockProductEntity.getOristockNum());
                    instockCost = Arith.add(instockCost, Arith.mul(warehouseOristockProductEntity.getOristockNum(), warehouseOristockProductEntity.getCost()));
                }
            }
            //计算流水结存
            Double num = Arith.sub(instockNum, outstockNum);
            Double cost = Arith.sub(instockCost, outstockCost);
            //计算第一条库存流水信息
            Double remainingStock,remainingCost;
            if (Objects.nonNull(stockFlowBillEntity)){
                if (Objects.equals(stockFlowBillEntity.getStockType(), StockTypeEnum.OUT_STOCK.getCode())){
                    Double productCost;
                    if (Objects.equals(num.compareTo(0.00) ,0)){
                        productCost = BasicConstant.ZERO_DOUBLE;
                    }else {
                        productCost = Arith.div(cost, num);
                    }
                    remainingStock = Arith.sub(num, stockFlowBillEntity.getNum());
                    remainingCost = Arith.sub(cost, Arith.mul(stockFlowBillEntity.getNum(), productCost));
                    stockFlowBillEntity.setProductCost(productCost);
                }else {
                    remainingStock = Arith.add(num, stockFlowBillEntity.getNum());
                    remainingCost = Arith.add(cost, Arith.mul(stockFlowBillEntity.getProductCost(), stockFlowBillEntity.getNum()));
                }
                stockFlowBillEntity.setRemainingStock(remainingStock);
                stockFlowBillEntity.setRemainingCost(remainingCost);
                stockFlowBillEntityList.add(stockFlowBillEntity);
            }
            //处理分仓结存信息
            StockSurplusRecordEntity stockSurplusRecordEntity = stockSurplusMap.get(productWarehouseEntity.getWarehouseKey());
            if (Objects.nonNull(stockSurplusRecordEntity)){
                stockSurplusRecordEntity.setRemainingStock(num);
                stockSurplusRecordEntity.setRemainingCost(cost);
                stockSurplusRecordEntList.add(stockSurplusRecordEntity);
            }
        }
        //处理批次信息
        List<BatchFlowBillEntity> batchFlowBillEntityList = new ArrayList<>();
        List<BatchSurplusRecordEntity> batchSurplusRecordEntList = new ArrayList<>();
        for (ProductStockEntity productStockEntity : productStockEntityList){
            Double instockNum = BasicConstant.ZERO_DOUBLE;
            Double outstockNum = BasicConstant.ZERO_DOUBLE;
            Double instockCost= BasicConstant.ZERO_DOUBLE;
            Double outstockCost = BasicConstant.ZERO_DOUBLE;
            //根据出入库时间获取第一条流水
            BatchFlowBillEntity batchFlowBillEntity = batchFlowBillModel.getBatchFlowBillBytime(corpid, productStockEntity.getProductId(), productStockEntity.getWarehouseId(), productStockEntity.getBatchKey());
            Map<String, Object> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            stockMap.put("corpid", corpid);
            stockMap.put("productId", productStockEntity.getProductId());
            stockMap.put("batch", productStockEntity.getBatch());
            stockMap.put("produceDate", productStockEntity.getProduceDate());
            stockMap.put("guaranteePeriod", productStockEntity.getGuaranteePeriod());
            stockMap.put("del", DelEnum.NORMAL.getDel());
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(stockMap);
            stockMap.put("warehouseId", productStockEntity.getWarehouseId());
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(stockMap);
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(stockMap);
            List<CostAdjustProductEntity> costAdjustProductEntityList = costAdjustProductModel.findEntitys(stockMap);
            //计算入库信息
            if (!instockProductEntityList.isEmpty()) {
                //入库单ID集合
                List<Long> idList = new ArrayList<>();
                //入库单id 集合
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                //获取入库单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(batchFlowBillEntity)){
                    filterMap.put("lessThanDate", batchFlowBillEntity.getDate());
                }
                List<InstockEntityExt> instockEntityList = instockModel.findEntitys(filterMap);
                instockEntityList.forEach(item -> {
                    idList.add(item.getId());
                });
                //计算入库结存
                for (InstockProductEntity instockProductEntity : instockProductEntityList) {
                    //判断该入库产品关联数据对应的入库单ID是否符合生成结存的时间范围
                    if (!idList.contains(instockProductEntity.getIntoWarehouseId())) {
                        continue;
                    }
                    instockNum = Arith.add(instockNum, instockProductEntity.getProductNum());
                    instockCost = Arith.add(instockCost, Arith.mul(instockProductEntity.getCost(), instockProductEntity.getProductNum()));
                }
            }
            //计算出库信息
            if (!outstockProductEntityList.isEmpty()) {
                //出库单ID集合
                List<Long> idList = new ArrayList<>();
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                //获取出库单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(batchFlowBillEntity)){
                    filterMap.put("lessThanDate", batchFlowBillEntity.getDate());
                }
                List<OutstockEntityExt> outstockEntityList = outstockModel.findEntitys(filterMap);
                outstockEntityList.forEach(item -> {
                    idList.add(item.getId());
                });
                for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                    if (!idList.contains(outstockProductEntity.getOutWarehouseId())) {
                        continue;
                    }
                    outstockNum = Arith.add(outstockNum, outstockProductEntity.getProductNum());
                    outstockCost = Arith.add(outstockCost, Arith.mul(outstockProductEntity.getCost(), outstockProductEntity.getProductNum()));
                }
            }
            //计算成本调整单信息
            if (!costAdjustProductEntityList.isEmpty()) {
                //成本调整单ID集合
                List<Long> idList = new ArrayList<>();
                List<Long> costAdjustIdList = new ArrayList<>();
                costAdjustProductEntityList.forEach(item -> costAdjustIdList.add(item.getCostAdjustId()));
                //获取成本调整单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", costAdjustIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(batchFlowBillEntity)){
                    filterMap.put("lessThanDate", batchFlowBillEntity.getDate());
                }
                List<CostAdjustEntityExt> costAdjustEntityExtList = costAdjustModel.findEntitys(filterMap);
                costAdjustEntityExtList.forEach(item -> {
                    idList.add(item.getId());
                });
                for (CostAdjustProductEntity costAdjustProductEntity : costAdjustProductEntityList) {
                    if (!idList.contains(costAdjustProductEntity.getCostAdjustId())) {
                        continue;
                    }
                    instockCost = Arith.add(instockCost, costAdjustProductEntity.getCostAdjustAmount().doubleValue());
                }
            }
            //计算期初信息
            if (!warehouseOristockProductEntityList.isEmpty()) {
                //期初ID集合
                List<Integer> idList = new ArrayList<>();
                List<Integer> oristockIdList = new ArrayList<>();
                warehouseOristockProductEntityList.forEach(item -> oristockIdList.add(item.getOristockId()));
                //获取成本调整单集合
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", oristockIdList);
                filterMap.put("del", DelEnum.NORMAL.getDel());
                List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(filterMap);
                warehouseOristockEntityList.forEach(item -> {
                    if(Objects.equals(productStockEntity.getWarehouseId(), item.getWarehouseId())){
                        idList.add(item.getId());
                    }
                });
                for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                    if (!idList.contains(warehouseOristockProductEntity.getOristockId())) {
                        continue;
                    }
                    if (Objects.nonNull(batchFlowBillEntity) && warehouseOristockProductEntity.getAddTime() >= batchFlowBillEntity.getDate()) {
                        continue;
                    }
                    instockNum = Arith.add(instockNum, warehouseOristockProductEntity.getOristockNum());
                    instockCost = Arith.add(instockCost, Arith.mul(warehouseOristockProductEntity.getOristockNum(), warehouseOristockProductEntity.getCost()));
                }
            }
            //计算流水结存
            Double num = Arith.sub(instockNum, outstockNum);
            Double cost = Arith.sub(instockCost, outstockCost);
            //计算信息
            Double remainingStock,remainingCost;
            if (Objects.nonNull(batchFlowBillEntity)){
                if (Objects.equals(batchFlowBillEntity.getStockType(), StockTypeEnum.OUT_STOCK.getCode())){
                    Double productCost;
                    if (Objects.equals(num.compareTo(0.00) ,0)){
                        productCost = BasicConstant.ZERO_DOUBLE;
                    }else {
                        productCost = Arith.div(cost, num);
                    }
                    remainingStock = Arith.sub(num, batchFlowBillEntity.getNum());
                    remainingCost = Arith.sub(cost, Arith.mul(batchFlowBillEntity.getNum(), productCost));
                    batchFlowBillEntity.setProductCost(productCost);
                }else {
                    remainingStock = Arith.add(num, batchFlowBillEntity.getNum());
                    remainingCost = Arith.add(cost, Arith.mul(batchFlowBillEntity.getProductCost(), batchFlowBillEntity.getNum()));
                }
                batchFlowBillEntity.setRemainingStock(remainingStock);
                batchFlowBillEntity.setRemainingCost(remainingCost);
                batchFlowBillEntityList.add(batchFlowBillEntity);
            }
            //处理批次结存信息
            BatchSurplusRecordEntity batchSurplusRecordEntity = batchSurplusMap.get(productStockEntity.getBatchKey());
            if (Objects.nonNull(batchSurplusRecordEntity)){
                batchSurplusRecordEntity.setRemainingStock(num);
                batchSurplusRecordEntity.setRemainingCost(cost);
                batchSurplusRecordEntList.add(batchSurplusRecordEntity);
            }
        }
        //更新流水
        if (CollectionsUtil.isNotEmpty(stockFlowBillEntityList)){
            stockFlowBillModel.updateStockFlowById(stockFlowBillEntityList, corpid);
        }
        if (CollectionsUtil.isNotEmpty(batchFlowBillEntityList)){
            batchFlowBillModel.updateBatchFlowById(batchFlowBillEntityList, corpid);
        }
        //更新结存
        if (CollectionsUtil.isNotEmpty(stockSurplusRecordEntList)){
            stockSurplusRecordModel.updateBatch(stockSurplusRecordEntList, corpid);
        }
        if (CollectionsUtil.isNotEmpty(batchSurplusRecordEntList)){
            batchSurplusRecordModel.updateBatch(batchSurplusRecordEntList, corpid);
        }
        //获取产品信息
        List<ProductEntityExt> productEntityExtList = productModel.getProductListByIdIn(corpid, dataIdList, 0);
        //拼装重算参数
        JSONArray productArray = new JSONArray();
        productEntityExtList.forEach(productEntityExt -> {
            JSONObject data = productEntityExt.getData();
            Integer enableBatch = data.getInteger(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());
            if (Objects.equals(0, enableBatch)){
                for (ProductWarehouseEntity productWarehouseEntity : productWarehouseEntityList){
                    if (!Objects.equals(productWarehouseEntity.getProductId(), productEntityExt.getId())){
                        continue;
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(SelectProductEnum.PRODUCT.getAttr(), productWarehouseEntity.getProductId());
                    jsonObject.put(SelectProductEnum.WAREHOUSE.getAttr(), productWarehouseEntity.getWarehouseId());
                    jsonObject.put(SelectProductEnum.UNIT.getAttr(), data.get(ProductEnum.UNIT.getAttr()));
                    jsonObject.put(ProductEnum.PARENT_ID.getSaasAttr(), productWarehouseEntity.getParentId());
                    jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), data.get(ProductEnum.ENABLE_MULTI_UNIT.getAttr()));
                    productArray.add(jsonObject);
                }
            }else {
                for (ProductStockEntity productStockEntity : productStockEntityList){
                    if (!Objects.equals(productStockEntity.getProductId(), productEntityExt.getId())){
                        continue;
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(SelectProductEnum.PRODUCT.getAttr(), productStockEntity.getProductId());
                    jsonObject.put(SelectProductEnum.WAREHOUSE.getAttr(), productStockEntity.getWarehouseId());
                    jsonObject.put(SelectProductEnum.UNIT.getAttr(), data.get(ProductEnum.UNIT.getAttr()));
                    jsonObject.put(ProductEnum.PARENT_ID.getSaasAttr(), productStockEntity.getParentId());
                    jsonObject.put(SelectProductEnum.EXPIRE_DATE.getAttr(), productStockEntity.getExpireDate());
                    jsonObject.put(SelectProductEnum.PRODUCE_DATE.getAttr(), productStockEntity.getProduceDate());
                    jsonObject.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), productStockEntity.getGuaranteePeriod()/86400);
                    jsonObject.put(SelectProductEnum.BATCH.getAttr(), productStockEntity.getBatch());
                    jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), data.get(ProductEnum.ENABLE_MULTI_UNIT.getAttr()));
                    productArray.add(jsonObject);
                }
            }
        });
        //调用统一的重算方法
        JSONObject data = new JSONObject();
        if (!productArray.isEmpty()) {
            LOG.warn("重算产品数据："+productArray.toJSONString());
            data.put(OutstockEnum.PRODUCT.getAttr(), productArray);
            data.put(OutstockEnum.TIME.getAttr(), time);
            CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
            costRecalculationDTO.setType(StockTypeEnum.IN_STOCK.getCode());
            costRecalculationDTO.setData(data);
            costRecalculationDTO.setCorpid(corpid);
            costRecalculationDTO.setMark(BasicConstant.THREE);
            costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
            costRecalculationProducer.sendMessage(costRecalculationDTO);
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("重算流水结束！");
        return "success";
    }

    /**
     * 某家公司重新刷流水并且修复库存
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixJxcStockData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixJxcStockData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("修复公司进销存库存&流水数据 begin。。。。。。。");
        long start = DateTimeUtil.getInt();
        List<String> corpidList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList()) && fixDataJobDTO.getCorpidList().size() == 1) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        String corpid = corpidList.get(0);
        try {
            //修复批次库存数据
            this.fixBatchStcok(corpid);
            //修复仓库库存数据
            this.fixWarehoseStcok(corpid);
            //生成流水
            this.fixStockFlowBillOneCompany(corpid);
        } catch (Exception e) {
            LOG.error("失败了,公司ID是" + corpid + "错误信息" + e);
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("修复公司进销存库存/流水数据 结束！");
        return "success";
    }

    private void fixBatchStcok(String corpid) throws XbbException{
        LOG.warn("fixAllBatchStock begin");
        //0普通模式，不过滤出入库产品，不插入分仓数据；1高级模式，过滤出入库产品，插入未匹配到的分仓数据
        Long dataDataMark = 0L;
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.mustNot(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID), 0));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PRODUCT, dataDataMark);
        paasFormDataEntityExtList = listVO.getList();
        dataDataMark = listVO.getDataIdMark();
        if (paasFormDataEntityExtList.isEmpty()) {
//                if (dataDataMark <= 0L){
//                    return "When I hit the question mark, it wasn't me that asked the question, but I thought you had the question.";
//                }
            throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212013);
        }
        List<Long> productIdList = new ArrayList<>();
        paasFormDataEntityExtList.forEach(item -> {
            productIdList.add(item.getDataId());
        });

        //入库
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", corpid);
        map.put("productIdIn", productIdList);
        map.put("del", 0);
        List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
        List<Long> idList = new ArrayList<>();
        if (!instockProductEntityList.isEmpty()) {
            List<Long> instockIdList = new ArrayList<>();
            instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
            Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            filterMap.put(StringConstant.CORPID, corpid);
            filterMap.put("idIn", instockIdList);
            filterMap.put("del", 0);
            idList = instockModel.findIds(filterMap);
        }
        removeAddData(idList, corpid);
        Map<String, Double> productWarehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (InstockProductEntity entity : instockProductEntityList) {
            if (!idList.contains(entity.getIntoWarehouseId())) {
                continue;
            }
            //batch
            String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
            Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key, 0D);
            productWarehouseStock = Arith.add(productWarehouseStock, entity.getProductNum());
            productWarehouseStockMap.put(key, productWarehouseStock);
        }
        //出库
        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
        idList = new ArrayList<>();
        if (!outstockProductEntityList.isEmpty()) {
            List<Long> outstockIdList = new ArrayList<>();
            outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
            Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            filterMap.put(StringConstant.CORPID, corpid);
            filterMap.put("idIn", outstockIdList);
            filterMap.put("del", 0);
            idList = outstockModel.findIds(filterMap);
        }
        removeAddData(idList, corpid);
        for (OutstockProductEntity entity : outstockProductEntityList) {
            if (!idList.contains(entity.getOutWarehouseId())) {
                continue;
            }
            //batch
            String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
            Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key, 0D);
            productWarehouseStock = Arith.sub(productWarehouseStock, entity.getProductNum());
            productWarehouseStockMap.put(key, productWarehouseStock);
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("productIdIn", productIdList);
        List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
        Map<Long, Long> oriWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        warehouseOristockEntityList.forEach(item -> oriWarehouseMap.put(item.getId().longValue(), item.getWarehouseId()));
        param.put("oriStockIdIn", oriWarehouseMap.keySet());
        param.put("productIdIn", productIdList);
        List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
        for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
            if (oriWarehouseMap.containsKey(warehouseOristockProductEntity.getOristockId().longValue())) {
                Long warehouseId = oriWarehouseMap.get(warehouseOristockProductEntity.getOristockId().longValue());
                String key = warehouseOristockProductEntity.getProductId() + "_" + warehouseId + "_" + warehouseOristockProductEntity.getBatch() + "_" + warehouseOristockProductEntity.getProduceDate() + "_" + warehouseOristockProductEntity.getGuaranteePeriod();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key, 0D);
                productWarehouseStock = Arith.add(productWarehouseStock, warehouseOristockProductEntity.getOristockNum());
                productWarehouseStockMap.put(key, productWarehouseStock);
            }
        }
        //分仓
        boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED), 1));
        boolQueryBuilder.filter(termsQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), productIdList));
        List<PaasFormDataEntity> productStockEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList("corpid", "id", ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.PRODUCT_ID), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.WAREHOUSE_ID), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.BATCH), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.PRODUCE_DATE), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.GUARANTEE_PERIOD)));
        List<ProductStockEntity> productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(productStockEntityList);

        List<ProductStockEntity> updateProductStockList = new ArrayList<>();
        for (ProductStockEntity entity : productStockEntities) {
            String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
            if (productWarehouseStockMap.containsKey(key)) {
                entity.setNum(productWarehouseStockMap.get(key));
                productWarehouseStockMap.remove(key);
            } else {
                entity.setNum(0D);
            }
            updateProductStockList.add(entity);
        }
        if (!updateProductStockList.isEmpty()) {
            productStockModel.updateStockBatch(updateProductStockList, corpid);
        }
        LOG.warn("fixAllBatchStock over");
    }

    private void fixWarehoseStcok(String corpid) throws XbbException{
        Long idGte = 0L;
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        List<WarehouseEntityExt> warehouseEntityExtList = warehouseModel.findEntitys(param);
        List<Long> warehouseIdList = new ArrayList<>();
        warehouseEntityExtList.forEach(item -> warehouseIdList.add(item.getId()));
        warehouseIdList.add(-1L);
        while (true) {
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("dataParentIdGte",0L);
            param.put("idGte",idGte);
            param.put("pageSize",1000);
            param.put("orderByStr","id asc");
            List<ProductEntityExt> productEntityExtList = productModel.findEntitys(param);
            if (productEntityExtList.isEmpty()) {
                if (idGte <= 0L){
                    LOG.warn(JSONObject.toJSONString(param));
                }
                break;
            }
            LOG.warn("idGte:" + idGte);
            idGte = productEntityExtList.get(productEntityExtList.size()-1).getId();
            List<Long> productIdList = new ArrayList<>();
            productEntityExtList.forEach(item -> {
                productIdList.add(item.getId());
            });
            //入库
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("productIdIn",productIdList);
            map.put("warehouseIdIn",warehouseIdList);
            map.put("del",0);
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
            List<Long> idList = new ArrayList<>();
            if (!instockProductEntityList.isEmpty()) {
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", 0);
                idList = instockModel.findIds(filterMap);
            }
            // 去掉在新建进工作流的数据，这个时候，库存不能进行运算
            removeAddData(idList, corpid);
            Map<Long,Double> skuStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String,Double>  productWarehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityList){
                if (!idList.contains(entity.getIntoWarehouseId())){
                    continue;
                }
                //sku
                Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                skuStock = Arith.add(skuStock,entity.getProductNum());
                skuStockMap.put(entity.getProductId(),skuStock);
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.add(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            //出库
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
            idList = new ArrayList<>();
            if (!outstockProductEntityList.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", 0);
                idList = outstockModel.findIds(filterMap);
            }
            // 去掉在新建进工作流的数据，这个时候，库存不能进行运算
            removeAddData(idList, corpid);
            for (OutstockProductEntity entity : outstockProductEntityList){
                if (!idList.contains(entity.getOutWarehouseId())){
                    continue;
                }
                //sku
                Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                skuStock = Arith.sub(skuStock,entity.getProductNum());
                skuStockMap.put(entity.getProductId(),skuStock);
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.sub(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
            List<Long> oriWarehouseIdList = new ArrayList<>();
            Map<Long,Long> oriWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseOristockEntityList.forEach(item -> {
                oriWarehouseMap.put(item.getId().longValue(),item.getWarehouseId());
                oriWarehouseIdList.add(item.getWarehouseId());
            });
            param.put("oriStockIdIn",oriWarehouseMap.keySet());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
            for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                if (oriWarehouseMap.containsKey(warehouseOristockProductEntity.getOristockId().longValue())){
                    Long warehouseId = oriWarehouseMap.get(warehouseOristockProductEntity.getOristockId().longValue());
                    // 分仓库存
                    String key = warehouseOristockProductEntity.getProductId() + "_" + warehouseId;
                    Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                    productWarehouseStock = Arith.add(productWarehouseStock,warehouseOristockProductEntity.getOristockNum());
                    productWarehouseStockMap.put(key,productWarehouseStock);
                    // sku库存
                    Double skuStock = skuStockMap.getOrDefault(warehouseOristockProductEntity.getProductId(),0D);
                    skuStock = Arith.add(skuStock,warehouseOristockProductEntity.getOristockNum());
                    skuStockMap.put(warehouseOristockProductEntity.getProductId(),skuStock);
                }
            }
            //分仓
            param.clear();
            param.put("corpid",corpid);
            param.put("productIdIn",productIdList);
            param.put("warehouseChecked",1);
            param.put("del",0);
            param.put("columns","corpid,id,product_id,warehouse_id,cost,ori_num");
            List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
            List<ProductWarehouseEntity> updateProductWareouseList = new ArrayList<>();
            Iterator<ProductWarehouseEntity> iterator = productWarehouseEntityList.iterator();
            //由于可能有老期初，同时又有全仓记录，先循环分仓记录，兼容老期初，再更新全仓记录
            while (iterator.hasNext()) {
                ProductWarehouseEntity entity = iterator.next();
                if (!Objects.equals(entity.getWarehouseId(),0L)){
                    String key = entity.getProductId() + "_" + entity.getWarehouseId();
                    if (entity.getOriNum() > 0 && !oriWarehouseIdList.contains(entity.getWarehouseId())) {
                        //老期初
                        Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                        productWarehouseStock = Arith.add(productWarehouseStock,entity.getOriNum());
                        productWarehouseStockMap.put(key,productWarehouseStock);

                        Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                        skuStock = Arith.add(skuStock,entity.getOriNum());
                        skuStockMap.put(entity.getProductId(),skuStock);
                    }
                    if (productWarehouseStockMap.containsKey(key)){
                        if (Objects.equals(entity.getNum(), productWarehouseStockMap.get(key))) {
                            iterator.remove();
                            productWarehouseStockMap.remove(key);
                            continue;
                        }
                        entity.setNum(productWarehouseStockMap.get(key));
                        productWarehouseStockMap.remove(key);
                    }else {
                        entity.setNum(0D);
                    }
                    updateProductWareouseList.add(entity);
                    iterator.remove();
                }
            }
            //全仓记录
            for (ProductWarehouseEntity entity : productWarehouseEntityList){
                if (Objects.equals(entity.getWarehouseId(),0L)){
                    if (Objects.equals(entity.getNum(), skuStockMap.get(entity.getProductId()))) {
                        continue;
                    }
                    entity.setNum(skuStockMap.getOrDefault(entity.getProductId(),0D));
                    updateProductWareouseList.add(entity);
                }
            }
            if (!updateProductWareouseList.isEmpty()){
                productWarehouseModel.updateStockBatch(updateProductWareouseList,corpid);
            } else {
                LOG.warn("no product warehouse update");
            }
//			if (superType && !productWarehouseStockMap.isEmpty()){
//				//没有空，表示productWarehouse有缺失
//			}
            //sku
            List<UpdateDataEntity> updateList = new ArrayList<>();
            for (PaasFormDataEntityExt entityExt : productEntityExtList){
                Double stock = entityExt.getData().getDouble(ProductEnum.STOCK.getAttr());
                if (Objects.equals(stock, skuStockMap.get(entityExt.getId()))) {
                    continue;
                }
                JSONObject json = new JSONObject();
                json.put(ProductEnum.STOCK.getAttr(),skuStockMap.getOrDefault(entityExt.getId(),0D));
                updateList.add(ExplainUtil.getUpdateData(entityExt.getId(),json,corpid));
            }
            if (!updateList.isEmpty()){
                productModel.updateBatch(updateList,corpid);
            } else {
                LOG.warn("no product update");
            }
        }
        LOG.warn("fixAllStock over");
    }

    private void fixStockFlowBillOneCompany(String corpid) throws XbbException{
        //获取6个月前时间----为了刷当前时间半年内流水数据
        //优化，默认2年
        Long sixMonthAgo = DateTimeUtil.getTimestampByCalendarType(DateTimeUtil.getTodayInt(), -24, Calendar.MONTH);
        LOG.warn("刷流水生成的开始日期:" + sixMonthAgo);
        Long beforeSeconds = DateTimeUtil.getTodayInt() - sixMonthAgo;
        Map<String, Object> param = new HashMap<>();
        //单位秒
        Long todayInt = DateTimeUtil.getTodayInt();
        Long greaterThanDate = todayInt - beforeSeconds;
        param.put("greaterThanDate", greaterThanDate);
        Map<String, Object> paraMap = new HashMap<>();
        paraMap.put("date", sixMonthAgo);
        paraMap.put("corpidIn", Collections.singletonList(corpid));
        param.put("corpid",corpid);
        // 先删除后添加
        stockFlowBillModel.deleteAllByCorpId(corpid);
        batchFlowBillModel.deleteAllByCorpId(corpid);
        stockSurplusRecordModel.deleteAllByCorpId(corpid);
        batchSurplusRecordModel.deleteAllByCorpId(corpid);
        //初始化结余表数据
        // 插入，往前推批次流水，后面会更新
        batchSurplusRecordModel.batchInsertRecordsFromBatchStock(paraMap);
        // 插入当前分仓，往前推流水，后面会更新
        stockSurplusRecordModel.batchInsertRecordsFromProductWarehouse(paraMap);
        //每家公司生成流水
        LOG.warn("公司:" + corpid + "-------" + "开始刷入数据");
        long startTmie = DateTimeUtil.getInt();
        try {
            FlowBillInsertDTO flowBillInsertDTO = new FlowBillInsertDTO();
            flowBillInsertDTO.setCorpid(corpid);
            flowBillInsertDTO.setBeforeSeconds(beforeSeconds);
            flowBillInsertDTO.setCorpid(corpid);
            batchFlowBillService.insertBeforeBatchFlow(flowBillInsertDTO);
            stockFlowBillService.insertBeforeStockFlow(flowBillInsertDTO);
        } catch (Exception e) {
            LOG.error("公司" + corpid + "失败了" + e);
        }
        long endTmie = DateTimeUtil.getInt() - startTmie;
        LOG.warn("公司:" + corpid + "刷入完成------耗时: " + endTmie + "秒");
    }


    /**
     * 去掉新建进流程的数据
     * @param idList
     * @param corpid
     */
    private void removeAddData(List<Long> idList, String corpid) {
        if (CollectionsUtil.isNotEmpty(idList)) {
            if (!commonHelp.isOpenWorkFlow(corpid)) {
                // 检测是否开通了工作流
                return;
            }
            // 查询审批中的任务
            Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            filterMap.put(StringConstant.CORPID, corpid);
            filterMap.put("dataIdIn", idList);
            filterMap.put("del", 0);
            filterMap.put("flowStatusIn", FlowStatusEnum.inApproval());
            filterMap.put("columns", " id, data_id, flow_status");
            List<WorkflowTaskEntity> taskList = workflowTaskModel.findEntities(filterMap);
            if (CollectionsUtil.isNotEmpty(taskList)) {
                List<Long> taskIdList = new ArrayList<>();
                taskList.forEach(item->{
                    taskIdList.add(item.getId());
                });
                filterMap.clear();
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("taskIdIn", taskIdList);
                filterMap.put("del", 0);
                List<WorkflowTransferDataEntity> list = workflowTransferDataModel.findEntities(filterMap);
                if (CollectionsUtil.isNotEmpty(list)) {
                    WorkflowTransferPOJO workflowTransferPOJO;
                    for (WorkflowTransferDataEntity item : list) {
                        workflowTransferPOJO = JSON.parseObject(item.getData().toJSONString(), WorkflowTransferPOJO.class);
                        Integer operate = workflowTransferPOJO.getOperate();
                        if (Objects.equals(WorkflowOperateEnum.ADD.getType(), operate)) {
//                            移除掉新建的入库单或者出库单
                            // 工作流的新建时，入库产品表和出库产品表都会生成；但是库存并未增加，所以需要移除掉新建进工作流的入库单和出库单
                            idList.remove(workflowTransferPOJO.getData().getId());
                        }
                    }
                }
            }
        }
    }
}
